

#include "RPR_0521RS.h"

// Default constructor
RPR_0521RS::RPR_0521RS(uint8_t address)
{
  _address = address;
}

// Initialization function
uint8_t RPR_0521RS::init(uint8_t measurementTime, uint8_t ledCurrent)
{
    // TODO: implement gain and measurement time selection
  // gain and measurement time arrays
  uint8_t alsGainTable[4] = {1, 2, 64, 128};
  uint8_t psGainTable[3] = {1, 2, 4};
  uint16_t alsMeasureTimeTable[13] = {0, 0, 0, 0, 0, 100, 100, 100, 400, 400, 400, 400, 50};
  uint16_t psMeasureTimeTable[13] = {0, 10, 40, 100, 400, 50, 100, 400, 50, 100, 0, 400, 50};

  // check manufacturer and part ID
  if ((getRegValue(_address, RPR_0521RS_REG_SYSTEM_CONTROL, 5, 0) != RPR_0521RS_PART_ID) || (getRegValue(_address, RPR_0521RS_REG_MANUFACT_ID) != RPR_0521RS_MANUFACT_ID))
  {
    // if the IDs do not match cancel initialization
    return (1);
  }

  // set control registers according to datasheet and user settings
  setRegValue(_address, RPR_0521RS_REG_ALS_PS_CONTROL, RPR_0521RS_ALS_DATA0_GAIN_1 | RPR_0521RS_ALS_DATA1_GAIN_1 | ledCurrent);
  setRegValue(_address, RPR_0521RS_REG_PS_CONTROL, RPR_0521RS_PS_GAIN_1, 5, 4);
  setRegValue(_address, RPR_0521RS_REG_MODE_CONTROL, RPR_0521RS_ALS_ON | RPR_0521RS_PS_ON | measurementTime);


  // set gain and measurement time
  _alsData0Gain = alsGainTable[0];
  _alsData1Gain = alsGainTable[0];
  _alsMeasurementTime = alsMeasureTimeTable[measurementTime];

  return (0);
}

// Measurement function
uint8_t RPR_0521RS::measure(void)
{
  // TODO: implement interrupt

  // ambient light measurement
  uint16_t rawValue[2];
  float data0, data1, data1_0;

  // read raw 2-byte integer values
  rawValue[0] = ((uint16_t)getRegValue(_address, RPR_0521RS_REG_ALS_DATA0_MSB) << 8) | getRegValue(_address, RPR_0521RS_REG_ALS_DATA0_LSB);
  rawValue[1] = ((uint16_t)getRegValue(_address, RPR_0521RS_REG_ALS_DATA1_MSB) << 8) | getRegValue(_address, RPR_0521RS_REG_ALS_DATA1_LSB);

  // ESP_LOGI("RPR_0521RS", "alsTime:%d,%d,%d,%d", _alsMeasurementTime,_alsData0Gain,rawValue[0], rawValue[1]);
  // // intermediate calculations
  // data0 = (float)rawValue[0] * (100 / _alsMeasurementTime) / _alsData0Gain;
  // data1 = (float)rawValue[1] * (100 / _alsMeasurementTime) / _alsData1Gain;

  // // zero division check
  // if (data0 == 0)
  // {
  //   ambLight = 0;
  // }

  // data1_0 = data1 / data0;

  // // return real value in lx
  // if (data1_0 < 0.595)
  // {
  //   ambLight = 1.682 * data0 - 1.877 * data1;
  // }
  // else if (data1_0 < 1.015)
  // {
  //   ambLight = 0.644 * data0 - 0.132 * data1;
  // }
  // else if (data1_0 < 1.352)
  // {
  //   ambLight = 0.756 * data0 - 0.243 * data1;
  // }
  // else if (data1_0 < 3.053)
  // {
  //   ambLight = 0.766 * data0 - 0.250 * data1;
  // }

  // // proximity measurement
  // // read the proximity value (does not have a real unit, this will only tell you whether an object is closer than e.g. a few centimiters)
  // prox = ((uint16_t)getRegValue(_address, RPR_0521RS_REG_PS_DATA_MSB) << 8) | getRegValue(_address, RPR_0521RS_REG_PS_DATA_LSB);

  return (0);
}
